﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WoChu.DeliverCenter.Entity;
using WoChu.DeliverCenter.Repository;
using WoChu.Infrastructure.ModelCommmon;
using WoChu.WMS.Entity;
using WoChu.WMS.Repository;
using WoChu.Infrastructure.Collection;
using MB.Util;
using WoChu.WMS.Application.Dto;
using System.Threading;

namespace Business.Service
{
    public class SaleAPPService
    {
        public SaleAPPRepository _SaleAPPRepository = new SaleAPPRepository();
        public DeliOrderRepository _DeliOrderRepository = new DeliOrderRepository();
        public DeliOrderDetailRepository _DeliOrderDetailRepository = new DeliOrderDetailRepository();
        public const string MsgFormate = "{0}不一致，原始数据：{1} 后台系统:{2}";

        /// <summary>
        /// 读取不一致的订单信息 ，从配送中心和erp数据库读取对应数据
        /// 1.首先判断是否有未导入，且根据订单号排除（串行读取）
        /// 2.在读取交集订单，若有错误的，记录总数（并行读取）
        /// 3.若未导入的显示当前页不够，则在读取剩余的交集的明细错误（并行读取），结果加载未导入后面，但是自身集合订单号排序
        /// 排序规则：先显示未导入的订单号升序 ，若现实不够，这交集的订单号升序
        /// </summary>
        /// <param name="pageInfo"></param>
        public void GetCheckOrderList(PageInfo<CheckOrder, CheckOrderInput> pageInfo)
        {
            if (pageInfo.Condition == null)
                throw new Exception("请输入条件");
            TraceEx.Write(string.Format("GetCheckOrderList开始加载", DateTime.Now), APPMessageType.CodeRunInfo);
            var condition = pageInfo.Condition;

            var sourceOrderList = _DeliOrderRepository.GetCheckList(new DeliOrder() { DeliveryPeriod = condition.DeliverDate, OrderNo = condition.OrderNo });
            TraceEx.Write(string.Format("sourceOrderList加载结束", DateTime.Now), APPMessageType.CodeRunInfo);
            var desOrderList = _SaleAPPRepository.GetCheckList(new SaleAPP() { RATIONDATE = Convert.ToDateTime(condition.DeliverDate), SHEETID = condition.OrderNo }) ?? new List<SaleAPP>();
            TraceEx.Write(string.Format("desOrderList加载结束", DateTime.Now), APPMessageType.CodeRunInfo);

            if (sourceOrderList.IsNullOrEmpty<DeliOrder>())
                return;

            var sorIds = sourceOrderList.Select(s => s.OrderNo);
            var desIds = desOrderList.Select(s => s.SHEETID);
            var addIds = sorIds.Except(desIds);
            //string[] slist ={"H0160509103127071","I0160509105837552","I0160507052457152","A0160507095822421",//
            //          "I0160509100841802"  ,"I0160509172105472","I0160509172827592","I0160509191701252","H2160509185937311"
            //               };
            var existsIds = sorIds.Intersect(desIds);
            var addList = sourceOrderList.Where(s => addIds.Count(n => n == s.OrderNo) > 0).OrderBy(s => s.OrderNo);
            addList.Foreach(s =>
            {
                AddCheckOrder(new CheckOrder() { OrderNo = s.OrderNo, CheckErrorInfo = "未导入" }, pageInfo);
            });

            Dictionary<string, CheckOrder> checks = new Dictionary<string, CheckOrder>();
            //existsIds.ToList().ForEach(s =>   
            Parallel.ForEach(existsIds, s =>
            {
                string error = GetCheckOrderError(sourceOrderList.First(i => i.OrderNo == s), desOrderList.First(i => i.SHEETID == s), pageInfo);
                //TraceEx.Write(string.Format("GetCheckOrderError加载结束{0}", error), APPMessageType.CodeRunInfo);
                if (!string.IsNullOrEmpty(error))
                {
                    checks.Add(s, new CheckOrder() { OrderNo = s });
                    //AddCheckOrder(new CheckOrder() { OrderNo = s, CheckErrorInfo = error }, pageInfo);
                }
            });
            pageInfo.Total += checks.Count;
            TraceEx.Write(string.Format("订单信息校验总数结束{0}", pageInfo.Total), APPMessageType.CodeRunInfo);
            #region 若要加载交集的订单错误信息
            if (pageInfo.Result.Count < pageInfo.PageSize && checks.Count > 0)
            {
                int stotal = pageInfo.Result.Count;
                int start = (pageInfo.PageIndex - 1) * pageInfo.PageSize;
                int skip = 0, take = pageInfo.PageSize;
                if (stotal < start)
                    skip = start - stotal;
                if (stotal > start)
                    take -= (stotal - start);
                var chkList = checks.OrderBy(s => s.Key).Skip(skip).Take(take);
                if (chkList.Count() > 0)
                {
                    //并行加载chkList错误信息
                    Parallel.ForEach(chkList, s =>
                    {
                        string error = GetCheckOrderError(sourceOrderList.First(i => i.OrderNo == s.Key), desOrderList.First(i => i.SHEETID == s.Key), pageInfo);

                        if (!string.IsNullOrEmpty(error))
                        {
                            s.Value.CheckErrorInfo = error;
                            //pageInfo.Result.Add(new CheckOrder() { OrderNo = s, CheckErrorInfo = error });
                            //AddCheckOrder(new CheckOrder() { OrderNo = s, CheckErrorInfo = error }, pageInfo);
                        }
                    });
                    TraceEx.Write(string.Format("订单信息校验展示列表添加结束{0}", chkList.Count()), APPMessageType.CodeRunInfo);
                }
                var existslist = chkList.Select(s => s.Value).OrderBy(s => s.OrderNo);
                if (pageInfo.Result.Count > 0)
                {
                    pageInfo.Result = pageInfo.Result.Union(existslist).ToList();
                }
                else
                    pageInfo.Result = existslist.ToList();
            }
            #endregion

            TraceEx.Write(string.Format("GetCheckOrderList加载结束", DateTime.Now), APPMessageType.CodeRunInfo);
        }


        private string GetCheckOrderError(DeliOrder souOrder, SaleAPP desOrder, PageInfo<CheckOrder, CheckOrderInput> pageInfo)
        {
            List<string> errors = new List<string>();
            string error = "";
            if (souOrder.OrderStatus != (byte)desOrder.SALEORDERFLAG)
            {
                error = string.Format(MsgFormate, "订单状态类型", souOrder.OrderStatus, desOrder.SALEORDERFLAG);
                if (AddError(ref errors, pageInfo, error)) return error;
            }
            if (souOrder.DeliveryStatus != desOrder.DELIVERYSTATUS)
            {
                error = string.Format(MsgFormate, "配送单状态", souOrder.DeliveryStatus, desOrder.DELIVERYSTATUS);
                if (AddError(ref errors, pageInfo, error)) return error;
            }
            string deliveryPeriod = string.Format("{0:yyyy-MM-dd} {1}", desOrder.RATIONDATE, desOrder.DeliveryTimePeriod);
            if (souOrder.DeliveryPeriod != string.Format("{0:yyyy-MM-dd} {1}", desOrder.RATIONDATE, desOrder.DeliveryTimePeriod))
            {
                error = string.Format(MsgFormate, "配送时段", souOrder.DeliveryPeriod, deliveryPeriod);
                if (AddError(ref errors, pageInfo, error)) return error;
            }
            if (souOrder.PointName != desOrder.POINTNAME)
            {
                error = string.Format(MsgFormate, "自提点地址(第三方配送)", souOrder.PointName, desOrder.POINTNAME);
                if (AddError(ref errors, pageInfo, error)) return error;
            }
            if (souOrder.SiteID != desOrder.SITEID)
            {
                error = string.Format(MsgFormate, "配送站点ID", souOrder.SiteID, desOrder.SITEID);
                if (AddError(ref errors, pageInfo, error)) return error;
            }
            string batchNo = null, batchSubNo = null, apporderno = desOrder.APPORDERNO;
            if (!string.IsNullOrEmpty(desOrder.APPORDERNO))
            {
                batchNo = apporderno.Split('-')[0];
                batchSubNo = apporderno.Split('-')[1];
            }
            if (souOrder.BatchNo != batchNo)
            {
                error = string.Format(MsgFormate, "批次号", souOrder.BatchNo, batchNo);
                if (AddError(ref errors, pageInfo, error)) return error;
            }
            if (souOrder.BatchSubNo != batchSubNo)
            {
                error = string.Format(MsgFormate, "批次子号", souOrder.BatchSubNo, batchSubNo);
                if (AddError(ref errors, pageInfo, error)) return error;
            }
            if (souOrder.TicketNo != desOrder.TICKETNO)
            {
                error = string.Format(MsgFormate, "票号", souOrder.TicketNo, desOrder.TICKETNO);
                if (AddError(ref errors, pageInfo, error)) return error;
            }

            #region 订单明细
            var sourceItems = new List<DeliOrderDetail>();
            // lock (_Lock)
            {
                DeliOrderDetailRepository deliOrderDetailRepository = new DeliOrderDetailRepository();
                sourceItems = deliOrderDetailRepository.GetCheckOrderDetailList(new DeliOrderDetail() { OrderNo = souOrder.OrderNo });
                // sourceItems = _DeliOrderDetailRepository.GetCheckOrderDetailList(new DeliOrderDetail() { OrderNo = souOrder.OrderNo });

            }
            if (!sourceItems.IsNullOrEmpty<DeliOrderDetail>())
            {
                var desItems = desOrder.SaleAPPItemList.GroupBy(s => new { SHEETID = s.SHEETID, s.REMARK })
                                .Select(g => new { SHEETID = g.Key.SHEETID, REMARK = g.Key.REMARK, QTY = g.Sum(i => i.QTY) });
                var sorIds = sourceItems.Select(s => s.GoodsNo);
                var desIds = desItems.Select(s => s.REMARK);
                var addIds = sorIds.Except(desIds);
                var existsIds = sorIds.Intersect(desIds);

                if (addIds.Count() > 0)
                {
                    error = string.Format("未导入的订单明细商品编号：{0}", string.Join(",", addIds));
                    if (AddError(ref errors, pageInfo, error)) return error;
                }

                existsIds.ToList().ForEach(s =>
                {
                    var sourceItem = sourceItems.First(i => i.GoodsNo == s);
                    var desItem = desItems.First(i => i.REMARK == s);

                    if (sourceItem.GoodsQty != desItem.QTY)
                    {
                        error = string.Format("订单明细商品编号:{0} 数量不一致，原始数据：{1} 后台系统:{2}", s, sourceItem.GoodsQty, desItem.QTY);
                        if (AddError(ref errors, pageInfo, error)) return;
                    }
                });
            }
            #endregion

            string errorMsg = "";
            if (errors.Count > 0)
                errorMsg = string.Join("<br/>", errors);
            return errorMsg;
        }

        void AddCheckOrder(CheckOrder cOrder, PageInfo<CheckOrder, CheckOrderInput> pageInfo)
        {
            bool isAdd = IsAdd(pageInfo);
            //TraceEx.Write(string.Format("AddCheckOrder isadd{0}", isAdd), APPMessageType.CodeRunInfo);
            if (isAdd)
                pageInfo.Result.Add(cOrder);
            pageInfo.Total++;
        }

        /// <summary>
        /// 若非添加元素，这只要有错误就返回true(代表立即结束）
        /// </summary>
        /// <param name="list"></param>
        /// <param name="pageInfo"></param>
        /// <param name="error"></param>
        /// <returns></returns>
        bool AddError(ref List<string> list, PageInfo<CheckOrder, CheckOrderInput> pageInfo, string error)
        {
            if (!string.IsNullOrEmpty(error))
            {
                list.Add(error);
            }

            return !IsAdd(pageInfo) && list.Count > 0;
        }

        bool IsAdd(PageInfo<CheckOrder, CheckOrderInput> pageInfo)
        {
            //lock (_Lock)
            {
                int start = (pageInfo.PageIndex - 1) * pageInfo.PageSize;
                int end = (pageInfo.PageIndex) * pageInfo.PageSize;
                int total = pageInfo.Total;
                return pageInfo.Result.Count < pageInfo.PageSize && (total >= start && total < end);
            }
        }
    }


}
